package com.supermarket.aspect;

import com.supermarket.annotation.OperationLogAnnotation;
import com.supermarket.context.UserContext;
import com.supermarket.entity.OperationLog;
import com.supermarket.service.OperationLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
@Slf4j
public class OperationLogAspect {

    @Autowired
    private OperationLogService operationLogService;

    // 定义切点
    @Pointcut("@annotation(com.supermarket.annotation.OperationLogAnnotation)")
    public void operationLogPointcut() {
    }

    // 环绕通知
    @Around("operationLogPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            // 执行原方法
            result = joinPoint.proceed();
            // 记录操作日志
            saveOperationLog(joinPoint, null);
            return result;
        } catch (Exception e) {
            // 记录操作日志（包含异常信息）
            saveOperationLog(joinPoint, e);
            throw e;
        }
    }

    // 保存操作日志
    private void saveOperationLog(ProceedingJoinPoint joinPoint, Exception e) {
        try {
            // 获取当前请求对象
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();

            // 获取注解信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);

            // 构建操作日志
            OperationLog operationLog = OperationLog.builder()
                    .userId(UserContext.getCurrentId())
                    .operation(annotation.operation())
                    .operationType(annotation.operationType())
                    .ipAddress(getIpAddress(request))
                    .createTime(LocalDateTime.now())
                    .build();

            // 如果有异常，在操作内容中添加异常信息
            if (e != null) {
                operationLog.setOperation(operationLog.getOperation() + " [异常: " + e.getMessage() + "]");
            }

            // 保存日志
            operationLogService.recordLog(operationLog);
        } catch (Exception ex) {
            log.error("记录操作日志失败", ex);
        }
    }

    // 获取IP地址
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
} 